package org.jeecg.modules.online.low.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtil;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.online.low.constant.LowAppMenuType;
import org.jeecg.modules.online.low.entity.LowAppMenu;
import org.jeecg.modules.online.low.mapper.LowAppMenuMapper;
import org.jeecg.modules.online.low.service.ILowAppMenuService;
import org.jeecg.modules.online.low.vo.LowAppMenuVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: low_app_menu
 * @Author: jeecg-boot
 * @Date: 2021-07-13
 * @Version: V1.0
 */
@Service("lowAppMenuServiceImpl")
public class LowAppMenuServiceImpl extends ServiceImpl<LowAppMenuMapper, LowAppMenu> implements ILowAppMenuService {

    @Override
    public List<LowAppMenuVo> listAndChildren(String appId) {
        LambdaQueryWrapper<LowAppMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LowAppMenu::getAppId, appId);
        queryWrapper.orderByAsc(LowAppMenu::getParentId);
        queryWrapper.orderByAsc(LowAppMenu::getOrderNum);
        List<LowAppMenu> menuList = super.list(queryWrapper);
        List<LowAppMenuVo> filterList = new ArrayList<>(menuList.size());
        // 分组
        Map<String, List<LowAppMenuVo>> groupMap = new HashMap<>();
        for (LowAppMenu menu : menuList) {
            LowAppMenuVo vo = new LowAppMenuVo(menu);
            // 菜单类型是分组
            if (LowAppMenuType.GROUP.equals(vo.getType())) {
                List<LowAppMenuVo> children = groupMap.get(vo.getId());
                if (children == null) {
                    children = new ArrayList<>();
                }
                groupMap.put(vo.getId(), children);
                vo.setChildren(children);
                filterList.add(vo);
            } else if (StringUtil.isNotEmpty(vo.getParentId())) {
                // 有父ID代表是子级，添加到父菜单中
                List<LowAppMenuVo> children = groupMap.get(vo.getParentId());
                if (children == null) {
                    children = new ArrayList<>();
                }
                children.add(vo);
                groupMap.put(vo.getParentId(), children);
            } else {
                filterList.add(vo);
            }
            // 如果是Online表单，就把主题模板查询出来
            if (LowAppMenuType.CGFORM.equals(vo.getType())) {
                JSONObject cgform = baseMapper.queryCgformDetail(vo.getMenuUrl());
                if (cgform != null) {
                    vo.setCgformIsTree(cgform.getString("is_tree"));
                    vo.setCgformThemeTemplate(cgform.getString("theme_template"));
                }
            }
        }
        return filterList;
    }

    @Override
    public int calcOrderNum(String appId, String parentId) {
        // 查出来当前app菜单的数量，然后设置orderNum
        LambdaQueryWrapper<LowAppMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LowAppMenu::getAppId, appId);
        // 如果是在分组内的菜单，就按照分组内的排序
        if (StringUtil.isNotEmpty(parentId)) {
            queryWrapper.eq(LowAppMenu::getParentId, parentId);
        } else {
            queryWrapper.eq(LowAppMenu::getParentId, "");
        }
        int count = super.count(queryWrapper);
        return count + 1;
    }

    @Override
    public boolean saveMenu(LowAppMenu menu) {
        int newOrderNum = this.calcOrderNum(menu.getAppId(), menu.getParentId());
        menu.setOrderNum(newOrderNum);
        if (menu.getParentId() == null) {
            menu.setParentId("");
        }
        return super.save(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean moveToGroup(LowAppMenu menu) {
        LowAppMenu oldMenu = super.getById(menu.getId());
        if (oldMenu == null) {
            throw new JeecgBootException("实体不存在");
        }
        String appId = oldMenu.getAppId();
        int orderNum;
        // parentId 为空，移出分组
        if (oConvertUtils.isEmpty(menu.getParentId())) {
            menu.setParentId("");
            orderNum = this.calcOrderNum(appId, "");
        } else {
            orderNum = this.calcOrderNum(appId, menu.getParentId());
        }
        menu.setOrderNum(orderNum);
        this.updateById(menu);
        // 老的分组、根目录下的排序也要重新计算下
        baseMapper.otherOrderNumMinus(appId, oldMenu.getParentId(), oldMenu.getOrderNum());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean orderToUp(LowAppMenu menu) {
        int orderNum = menu.getOrderNum();
        if (orderNum <= 1) {
            throw new JeecgBootException("已在最顶部");
        }
        return this.orderTo(menu, menu.getOrderNum() - 1);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean orderToDown(LowAppMenu menu) {
        int orderNum = menu.getOrderNum();
        int newOrderNum = this.calcOrderNum(menu.getAppId(), menu.getParentId());
        if ((orderNum + 1) >= newOrderNum) {
            throw new JeecgBootException("已在最底部");
        }
        return this.orderTo(menu, menu.getOrderNum() + 1);
    }

    /**
     * 调整菜单的排序，可将相邻的菜单同步更改
     *
     * @param menu        要排序的菜单
     * @param newOrderNum 新的排序位置
     * @return
     */
    private boolean orderTo(LowAppMenu menu, int newOrderNum) {
        // 拼接 queryWrapper  用于更新当前菜单相邻的菜单
        LambdaQueryWrapper<LowAppMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LowAppMenu::getOrderNum, newOrderNum);
        queryWrapper.eq(LowAppMenu::getAppId, menu.getAppId());
        // 如果是在分组内的菜单，就按照分组内的排序
        if (StringUtil.isNotEmpty(menu.getParentId())) {
            queryWrapper.eq(LowAppMenu::getParentId, menu.getParentId());
        } else {
            queryWrapper.eq(LowAppMenu::getParentId, "");
        }
        // 更新相邻的菜单
        LowAppMenu updateMenu = new LowAppMenu();
        updateMenu.setOrderNum(menu.getOrderNum());
        super.update(updateMenu, queryWrapper);
        // 更新当前的菜单
        menu.setOrderNum(newOrderNum);
        return super.updateById(menu);
    }

    @Override
    public List<LowAppMenu> queryLogicDeleted() {
        return this.queryLogicDeleted(null);
    }

    @Override
    public List<LowAppMenu> queryLogicDeleted(LambdaQueryWrapper<LowAppMenu> wrapper) {
        if (wrapper == null) {
            wrapper = new LambdaQueryWrapper<>();
        }
        wrapper.eq(LowAppMenu::getDelFlag, CommonConstant.DEL_FLAG_1);
        return baseMapper.selectLogicDeleted(wrapper);
    }

    @Override
    public boolean revertLogicDeleted(List<String> idList, LowAppMenu updateEntity) {
        LambdaQueryWrapper<LowAppMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(LowAppMenu::getId, idList);
        return baseMapper.revertLogicDeleted(updateEntity, wrapper) > 0;
    }

    @Override
    public boolean removeLogicDeleted(List<String> idList) {
        LambdaQueryWrapper<LowAppMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(LowAppMenu::getId, idList);
        return baseMapper.deleteLogicDeleted(wrapper) > 0;
    }

    @Override
    public boolean forceRemove(LambdaQueryWrapper<LowAppMenu> wrapper) {
        return baseMapper.deleteLogicDeleted(wrapper) > 0;
    }

    @Override
    public boolean forceRemoveByDesformId(List<String> idList) {
        return baseMapper.deleteLogicDeletedByDesformId(idList) > 0;
    }

}
